package com.xhorse.lockplatform.comm.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.logging.Log;
import org.slf4j.Logger;

import java.beans.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Tom
 */
public class StringUtil {

    public StringUtil() {
    }

    public static final int PAD_STYLE_LEFT = 1;
    public static final int PAD_STYLE_RIGHT = 2;
    public static final int PAD_STYLE_BOTH = 3;

    /**
     * 空字符串和null字符串返回true
     *
     * @param string
     * @return
     */
    public static boolean isNil(String string) {
        return string == null || string.length() == 0;
    }

    public static boolean isNotNil(String string) {
        return !isNil(string);
    }

    /**
     * 空字符串集合和没有元素的字符串集合返回true
     *
     * @param strings
     * @return
     */
    public static boolean isNil(Collection<String> strings) {
        return strings == null || strings.isEmpty();
    }

    public static boolean isNil(String[] strings) {
        return strings == null || strings.length == 0;
    }

    public static boolean isNotNil(String[] strings) {
        return !isNil(strings);
    }

    public static boolean isNotNil(Collection<String> strings) {
        return !isNil(strings);
    }

    public static String[] createArray(List<String> strings) {
        String[] array = new String[strings.size()];
        for (int i = 0; i < strings.size(); i++) {
            array[i] = strings.get(i);
        }

        return array;
    }

    public static String trim(String string) {
        if (string == null) {
            return null;
        }

        return string.trim();
    }

    public static boolean isInStrings(String target, String... conditions) {
        for (String condition : conditions) {
            if (target.equals(condition)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isNumber(String str) {
        return Pattern.matches("[0-9]*", str);
    }

    /**
     * 在字符串str中每隔lineSize个字符插入一个回车
     *
     * @param str
     * @param lineSize
     */
    public static String insertEnterToString(String str, int lineSize) {
        if (str == null || "".equals(str)) {
            return null;
        }

        if (lineSize >= str.length() || lineSize <= 0) {
            return str;
        }

        StringBuilder resultStr = new StringBuilder();
        while (str.length() > lineSize) {
            resultStr.append(str.substring(0, lineSize)).append("\n\r");
            str = str.substring(lineSize);
        }
        resultStr.append(str);
        return resultStr.toString();
    }

    /**
     * 取字符串的 前length个字符
     *
     * @param str
     * @param length
     * @return
     */
    public static String subString(String str, int length) {
        if (isNil(str) || length <= 0) {
            return str;
        }

        return str.length() < length ? str : str.substring(0, length);
    }

    /**
     * 按字节长度截取字符串(支持截取带HTML代码样式的字符串)
     *
     * @param param  将要截取的字符串参数
     * @param length 截取的字节长度
     * @param end    字符串末尾补上的字符串
     * @return 返回截取后的字符串
     */
    public static String subStringHTML(String param, int length, String end) {
        StringBuilder result = new StringBuilder();
        int n = 0;
        char temp;
        // 是不是HTML代码
        boolean isCode = false;
        // 是不是HTML特殊字符,如&nbsp;
        boolean isHTML = false;
        for (int i = 0; i < param.length(); i++) {
            temp = param.charAt(i);
            if (temp == '<') {
                isCode = true;
            } else if (temp == '&') {
                isHTML = true;
            } else if (temp == '>' && isCode) {
                n = n - 1;
                isCode = false;
            } else if (temp == ';' && isHTML) {
                isHTML = false;
            }

            if (!isCode && !isHTML) {
                n = n + 1;
                // UNICODE码字符占两个字节
                if ((temp + "").getBytes().length > 1) {
                    n = n + 1;
                }
            }

            result.append(temp);
            if (n >= length) {
                break;
            }
        }

        result.append(end);

        // 取出截取字符串中的HTML标记
        String tempResult = result.toString().replaceAll("(>)[^<>]*(<?)",
                "$1$2");
        // 去掉不需要结素标记的HTML标记
        tempResult = tempResult
                .replaceAll(
                        "</?(AREA|BASE|BASEFONT|BODY|BR|COL|COLGROUP|DD|DT|FRAME|HEAD|"
                                + "HR|HTML|IMG|INPUT|ISINDEX|LI|LINK|META|OPTION|P|PARAM|TBODY|TD|TFOOT|TH|THEAD|TR" +
                                "|area|base|basefont|"
                                + "body|br|col|colgroup|dd|dt|frame|head|hr|html|img|input|isindex|li|link|meta" +
                                "|option|p|param|tbody|td|tfoot|th|thead|tr)[^<>]*/?>",
                        "");
        // 去掉成对的HTML标记
        tempResult = tempResult.replaceAll("<([a-zA-Z]+)[^<>]*>(.*?)</\\1>",
                "$2");
        // 用正则表达式取出标记
        Pattern p = Pattern.compile("<([a-zA-Z]+)[^<>]*>");
        Matcher m = p.matcher(tempResult);

        List endHTML = new ArrayList();

        while (m.find()) {
            endHTML.add(m.group(1));
        }

        // 补全不成对的HTML标记
        for (int i = endHTML.size() - 1; i >= 0; i--) {
            result.append("</");
            result.append(endHTML.get(i));
            result.append(">");
        }

        return result.toString();
    }

    public static String limitStringByBytes(String value, int len) {
        if (isNil(value) || len <= 0) {
            return value;
        }
        if (value.getBytes().length <= len) {
            return value;
        }
        return new String(value.getBytes(), 0, len);
    }

    public static boolean validStringByBytes(String value, int len) {
        return isNil(value) || len <= 0 || value.getBytes().length <= len;
    }

    /**
     * null转换为""
     *
     * @param str
     * @return
     */
    public static String blankWhenNull(String str) {
        return str == null ? "" : str;
    }

    /**
     * null转换为"——"
     *
     * @param str
     * @return
     */
    public static String dashWhenNull(String str) {
        return str == null || ("").equals(str.trim()) ? "——" : str;
    }

    public static String getStringAfter(String s, String after) {
        int beginIndex = s.indexOf(after);
        if (s.length() == beginIndex + 1 || beginIndex == -1) {
            return "";
        }
        return s.substring(beginIndex + 1);
    }

    public static String right(String s, int length) {
        if (s == null) {
            return null;
        }

        assert length > 0 : "length must greater than zero";

        if (s.length() <= length) {
            return s;
        }

        return s.substring(s.length() - length, s.length());
    }

    public static String listToString(List<String> productTagList, String split) {
        if (productTagList == null || productTagList.isEmpty()) {
            return null;
        }
        StringBuilder r = new StringBuilder();
        for (String item : productTagList) {
            if (r.length() == 0) {
                r.append(item);
            } else if (item != null && item.length() > 0) {
                r.append(split).append(item);
            }
        }
        return r.toString();
    }

    public static String listToString(List<String> productTagList) {
        return listToString(productTagList, ",");
    }

    public static boolean isNullOrEmpty(String str) {
        return null == str || 0 == str.trim().length();
    }

    public static String pad(String str, String padStr, int padTimes,
                             int padStyle) {
        assert str != null : "填充目标为空";
        assert isNotNil(padStr) : "填充字符串为空";
        assert padTimes >= 0 : "填充次数小于0";

        StringBuilder actualPadStr = new StringBuilder();
        for (int i = 0; i < padTimes; i++) {
            actualPadStr.append(padStr);
        }
        if (PAD_STYLE_LEFT == padStyle) {
            return actualPadStr + str;
        } else if (PAD_STYLE_RIGHT == padStyle) {
            return str + actualPadStr;
        } else if (PAD_STYLE_BOTH == padStyle) {
            return actualPadStr + str + actualPadStr;
        } else {
            assert false : "不能识别填充模式";
        }
        return str;
    }

    public static String pad(String str, int padTimes) {
        return pad(str, " ", padTimes, PAD_STYLE_BOTH);
    }

    /**
     * 将String按len长度分割
     *
     * @param s
     * @param len
     * @return
     */
    public static List<String> partition(String s, int len) {
        List<String> ss = new ArrayList<>();
        if (s.length() > len) {
            do {
                ss.add(s.substring(0, len));
                s = s.substring(len);
            } while (s.length() > len);
        }
        ss.add(s);
        return ss;
    }

    @SuppressWarnings("unchecked")
    public static String removeSameString(String s) {
        StringTokenizer token = new StringTokenizer(s, ",");
        StringBuilder resultString = new StringBuilder();
        LinkedHashSet stringSet = new LinkedHashSet();
        int countTokens = token.countTokens();
        for (int i = 0; i < countTokens; i++) {
            stringSet.add(token.nextElement());
        }
        for (Object aStringSet : stringSet) {
            resultString.append((String) aStringSet).append(",");
        }
        if (StringUtil.isNotNil(resultString.toString())) {
            resultString = new StringBuilder(resultString.substring(0, resultString.length() - 1));
        }
        return resultString.toString();
    }

    public static String obj2xml(Object obj) {
        ByteArrayOutputStream o = new ByteArrayOutputStream();
        XMLEncoder e = new XMLEncoder(o);
        e.setPersistenceDelegate(BigDecimal.class,
                new DefaultPersistenceDelegate() {
                    @Override
                    protected Expression instantiate(Object oldInstance,
                                                     Encoder out) {
                        BigDecimal bd = (BigDecimal) oldInstance;
                        return new Expression(oldInstance, oldInstance
                                .getClass(), "new", new Object[]{bd
                                .toString()});
                    }
                });

        e.writeObject(obj);
        e.flush();
        e.close();
        return o.toString();
    }

    public static Object xml2obj(String xml) {
        ByteArrayInputStream i = new ByteArrayInputStream(xml.getBytes());
        XMLDecoder d = new XMLDecoder(i);
        Object obj = d.readObject();
        d.close();
        return obj;
    }

    @SuppressWarnings("unchecked")
    public static <T> T xml2obj(Class<T> clazz, String xml) {
        return (T) xml2obj(xml);
    }

    public static String arrayToString(Object[] list, String splitStr) {
        if (list == null) {
            return "";
        }

        StringBuilder row = new StringBuilder();
        for (Object aList : list) {
            row.append(aList == null ? splitStr : aList + splitStr);
        }
        row = new StringBuilder(row.substring(0, row.length() - splitStr.length()));
        return row.toString();
    }

    public static String objToStr(Object obj) {
        return obj == null ? "" : String.valueOf(obj);
    }

    /**
     * 得到字符串中的汉字
     */
    public static String getChineseCharacter(String str) {
        String regEx = "[\\u4e00-\\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        StringBuilder result = new StringBuilder();
        while (m.find()) {
            result.append(m.group(0));
        }
        return result.toString();
    }

    /**
     * 将发票号进行分割，分割成发票代码和发票编号
     *
     * @param noteNo
     * @return
     */
    public static String[] splitNoteNo(String noteNo) {
        if (noteNo == null) {
            noteNo = "";
        }
        String[] invoiceInfo = new String[2];
        if (noteNo.contains("-")) {
            invoiceInfo[0] = noteNo.split("-")[0];
            invoiceInfo[1] = noteNo.split("-")[1];
        } else {
            invoiceInfo[0] = "";
            invoiceInfo[1] = noteNo;

        }
        return invoiceInfo;
    }

    /**
     * 处理字符串为null以及对字符串进行trim操作
     */
    public static String dealNullAndTrimString(String str) {
        if (str == null || "".equals(str)) {
            return "";
        } else {
            return str.trim();
        }
    }

    /**
     * 根据传入字符串用英文逗号隔开，返回字符串List
     */
    public static List<String> split(String str) {
        return split(str, ",");
    }

    /**
     * 根据传入字符串和分隔符号隔开，返回字符串List
     */
    public static List<String> split(String str, String regex) {
        List<String> list = new ArrayList<String>();
        if (isNil(str)) {
            return list;
        }
        if (isNil(regex)) {
            list.add(str);
            return list;
        }
        String[] arr = str.split(regex);
        for (String a : arr) {
            if (isNil(a.trim())) {
                continue;
            }
            list.add(a.trim());
        }
        return list;
    }

    /**
     * 验证邮箱是否合法
     *
     * @param email
     * @return
     */
    public static boolean isEmail(String email) {
        String regex = "\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(email);
        return m.find();
    }

    /**
     * 验证手机号是否合法
     *
     * @param mobiles
     * @return
     */
    public static boolean isMobileNO(String mobiles) {
        return Pattern.matches("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$", mobiles);
    }

    /**
     * 转换为固定长度的数字，不足在前面补0
     *
     * @param srcInteger
     * @param totalLength
     * @return
     */
    public static String convertIntToString(int srcInteger, int totalLength) {
        StringBuilder targetStr = new StringBuilder();
        int count = totalLength - Integer.toString(srcInteger).length();
        for (int i = 0; i < count; i++) {
            targetStr.append("0");
        }
        targetStr.append(srcInteger);
        return targetStr.toString();
    }

    /**
     * BigDecimal转为String 精确到小数点后两位
     *
     * @param value
     * @return
     */
    public static String convertBigDecimalToString(BigDecimal value) {
        if (value == null) {
            return "0.00";
        }
        value = value.setScale(2, BigDecimal.ROUND_HALF_UP);
        return value.toString();
    }

    public static String fixedLength(String input, int len) {
        return input == null || input.length() <= len ? input : input.substring(0, len);
    }

    public static String subString(String str, int begin, int end) {
        return StringUtil.blankWhenNull(str).length() < end ? "" : str.substring(begin, end);
    }

    /**
     * 处理通过“_”标示的特殊字串
     *
     * @param str
     * @return
     */
    public static Tuple<String, String> splitStr(String str) {
        Tuple<String, String> tuple = new Tuple<>("", "");
        if (str == null || str.length() == 0 || str.split("_").length != 2) {
            return tuple;
        }

        String[] arr = str.split("_");
        tuple.first = arr[0];
        tuple.second = arr[1];

        return tuple;
    }

    /**
     * 判断字符串是否是JSON格式
     *
     * @param str    原始字符串
     * @param logger Logger
     * @return
     */
    public static boolean isJson(String str, Logger logger) {
        try {
            if (StringUtil.isNullOrEmpty(str)) {
                return false;
            }
            JSONObject.parseObject(str);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 求百分百
     *
     * @param numerator   分子
     * @param denominator 分母
     * @return
     */
    public static String percent(int numerator, int denominator) {
        if (denominator == 0) {
            return String.valueOf(0);
        }
        // 创建一个数值格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(2);
        return numberFormat.format((float) numerator / (float) denominator * 100) + "%";
    }

    public static int toInt(String s) {
        int result = 0;
        try {
            result = Integer.parseInt(s);
        } catch (NumberFormatException ignored) {
        }
        return result;
    }

    public static double toDouble(String s) {
        double result = 0;
        try {
            result = Double.parseDouble(s);
        } catch (NumberFormatException ignored) {
        }
        return result;
    }

    public String readStream(InputStream inputStream, Log logger) {
        byte[] bytes = new byte[1024 * 1024];

        int nRead = 1;
        int nTotalRead = 0;
        String str = null;
        try {
            while (nRead > 0) {
                nRead = inputStream.read(bytes, nTotalRead, bytes.length - nTotalRead);

                if (nRead > 0) {
                    nTotalRead = nTotalRead + nRead;
                }
            }

            str = new String(bytes, 0, nTotalRead);
        } catch (IOException e) {
            logger.error("StringUtil readStream error : ", e);
        }

        return str;
    }

    public static String getFileSize(long size) {
        //如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
        if (size < 1024) {
            return String.valueOf(size) + "B";
        } else {
            size = size / 1024;
        }
        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
        //因为还没有到达要使用另一个单位的时候
        //接下去以此类推
        if (size < 1024) {
            return String.valueOf(size) + "KB";
        } else {
            size = size / 1024;
        }
        if (size < 1024) {
            //因为如果以MB为单位的话，要保留最后1位小数，
            //因此，把此数乘以100之后再取余
            size = size * 100;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "MB";
        } else {
            //否则如果要以GB为单位的，先除于1024再作同样的处理
            size = size * 100 / 1024;
            return String.valueOf((size / 100)) + "."
                    + String.valueOf((size % 100)) + "GB";
        }
    }

    public static String getPrintSize(String size) {
        Tuple<String, String> tuple = StringUtil.splitStr(size);
        long available, total;
        String printSize = null;
        try {
            available = Long.parseLong(tuple.first);
            total = Long.parseLong(tuple.second);
            printSize = getFileSize(available) + "_" + getFileSize(total);
        } catch (NumberFormatException ignored) {
        }

        return StringUtil.isNil(printSize) ? "" : printSize;
    }

    /**
     * 正则表达式匹配两个指定字符串中间的内容
     *
     * @param soap
     * @return
     */
    public static List<String> getSubUtil(String soap, String regx) {
        List<String> list = new ArrayList<>();
        // 匹配的模式
        Pattern pattern = Pattern.compile(regx);
        Matcher m = pattern.matcher(soap);
        while (m.find()) {
            int i = 1;
            list.add(m.group(i));
            i++;
        }
        return list;
    }

    /**
     * 返回单个字符串，若匹配到多个的话就返回第一个，方法与getSubUtil一样
     *
     * @param soap
     * @param regx
     * @return
     */
    public static String getSubUtilSimple(String soap, String regx) {
        // 匹配的模式
        Pattern pattern = Pattern.compile(regx);
        Matcher m = pattern.matcher(soap);
        while (m.find()) {
            return m.group(1);
        }
        return "";
    }

    /**
     * 格式化显示字符串
     *
     * @param originText
     * @param type
     * @return
     */
    public static String formattedDisplay(String originText, String type) {
        String result = null;
        switch (type) {
            // 姓名
            case "name":
                if (originText.length() == 2) {
                    result = originText.substring(0, 1) + outputStar(originText.length() - 1);
                } else if (originText.length() > 2) {
                    result = originText.substring(0, 1) + outputStar(originText.length() - 2) + originText.substring
                            (originText.length() - 1, originText.length());
                }
                break;
            // 身份证号码
            case "ID":
                if (originText.length() == 18) {
                    result = originText.substring(0, 6) + outputStar(8) + originText.substring(14, 18);
                }
                break;
            // 手机号码
            case "mobi":
                if (originText.length() == 11) {
                    result = originText.substring(0, 3) + outputStar(4) + originText.substring(7, 11);
                }
                break;
            // 银行卡号
            case "card":
                if (originText.length() > 12) {
                    result = originText.substring(0, 6) + outputStar(originText.length() - 10) + originText.substring
                            (originText.length() - 4, originText.length());
                }
                break;
            default:
        }

        return result;
    }

    private static String outputStar(int length) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i < length; i++) {
            result.append("*");
        }

        return result.toString();
    }

    /**
     * 判断字符串是否是中文
     *
     * @param string
     *            要判断的字符串
     * @return
     */
    public static boolean isChineseStr(String string) {
        String regEx = "[\\u4e00-\\u9fa5]+";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(string);
        if (m.find())
            return true;
        else
            return false;
    }

    public static void main(String[] args) {
        System.out.println(formattedDisplay("王大锤", "name"));
        System.out.println(formattedDisplay("邓超", "name"));
        System.out.println(formattedDisplay("完颜阿骨打", "name"));
        System.out.println(formattedDisplay("431021198101024171", "ID"));
        System.out.println(formattedDisplay("18666200660", "mobi"));
        System.out.println(formattedDisplay("62251234567167", "card"));
    }
}
